#!/usr/bin/python
# -*- coding:UTF-8 -*-

import urllib
#import httplib
#import urllib2 
import time

from google.appengine.api import urlfetch

from xml.dom import minidom 
from xml.dom import Node

import methods
import utils
import api
import configs
import profilefield

from schema import XiaoneiException

class XiaoneiRestClient(object):
    'Xiaonei Client'
    TARGET_API_VERSION = "1.0"
    XN_SERVER = "api.xiaonei.com/restserver.do"
    SERVER_ADDR = "http://" + XN_SERVER
    HTTPS_SERVER_ADDR = "https://" + XN_SERVER
    SERVER_URL = SERVER_ADDR
    HTTPS_SERVER_URL = HTTPS_SERVER_ADDR
    NUM_AUTOAPPENDED_PARAMS = 6
    ERROR_TAG="error_response"
    __sessionKey = ""
    __apiKey = None

    __serverUrl=SERVER_URL
    __timeout = -1
    __userId = -1
    __secret=""
    __sessionSecret=""
    
    __isDebug=True
    __isDesktop=False

    ##@param:  paramPairs: a List of tuple(string,string)
    ##@return:  a dom document
    ##@raise exception: XiaoneiException 
    def __callMethod(self,method,paramPairs=None):
        params={}
        params['method']=method.methodName
        params['api_key']=self.__class__.__apiKey
        params['v']=self.TARGET_API_VERSION
        if methods.requireSession(method) and self.__sessionKey:
            params['call_id']=long(1000*time.time())
            params['session_key']=self.__sessionKey
        if paramPairs:
            for t in paramPairs:
                params[t[0]]=t[1]
        sig=self.generateSignature(utils.convert(params),methods.requireSession(method))
        params['sig']=sig
        doc=None
        try:
            doc=self.__class__.__postRequest(self,method, params, False, False)
        except:
            raise XiaoneiException("-1","request error")
        ##check error
        errors=doc.getElementsByTagName(self.__class__.ERROR_TAG)
        if errors.length>0:
            errorCode=errors.item(0).childNodes[0].firstChild.data
            print errorCode
            message = errors.item(0).childNodes[1].firstChild.data
            print message.encode("utf8")
            raise XiaoneiException(errorCode,message)
        self.stripEmptyTextNodes(doc)
        return doc
    
    def __postRequest(self,method,params,doHttps,doEncode):
        serverUrl=HTTPS_SERVER_URL if doHttps else self.__class__.__serverUrl
        #httplib.HTTPConnection.debuglevel = 1
        #print str(method)
        #print serverUrl
        data=urllib.urlencode(params)
        #print "POST data:",data
        #f=urllib2.urlopen(serverUrl,data)
        #xml=f.read()
        result=urlfetch.fetch(url=serverUrl,
                              payload=data,
                              method=urlfetch.POST,
                              headers={'Content-Type': 'application/x-www-form-urlencoded'})
        if result.status_code == 200:
            xml=result.content
        else:
            print result.status_code
            print result.content
        #print xml
        doc=minidom.parseString(xml)
        return doc
    
    def users_getLoggedInUser(self):
        if self.__class__.__userId==-1:
            d=self.__class__.__callMethod(self,methods.USERS_GET_LOGGED_IN_USER)
            self.__class__.__userId=api.getLoggedInUser(d)
        return self.__class__.__userId
    
    def users_isAppAdded(self,id=None):
        if id is None:
            d=self.__class__.__callMethod(self,methods.USERS_IS_APP_ADDED)
        else:
            p=[("uids",id)]
            d=self.__class__.__callMethod(self,methods.USERS_IS_APP_ADDED,p)        
        return api.isAppAdded(d)
    
    def users_getUserInfo(self,userids,fields):
        p=[]
        p.append(("uids",self.delimit(userids)))
        p.append(("fields",self.delimit(fields)))
        d=self.__class__.__callMethod(self,methods.USERS_GET_INFO,p)
        fields.append(profilefield.UID)
        return api.getUserInfo(d,fields)
    
    def friends_getFriends(self):
        d=self.__class__.__callMethod(self,methods.FRIENDS_GET_FRIENDS)
        return api.getFriends(d)
    
    def friends_get(self):
        d=self.__class__.__callMethod(self,methods.FRIENDS_GET)
        return api.getFriendIds(d)
    
    def friends_areFriends(self,uid1,uid2):
        p=[]
        p.append(("uids1",self.delimit(uid1)))
        p.append(("uids2",self.delimit(uid2)))
        d=self.__class__.__callMethod(self,methods.FRIENDS_ARE_FRIENDS,p)
        return api.areFriends(d)
        
    def __init__(self,apiKey,secret,sessionKey,serverUrl=SERVER_URL):
        self.__class__.__sessionKey = sessionKey
        self.__class__.__apiKey = apiKey
        self.__class__.__secret = secret
        self.__class__.__serverUrl = serverUrl
        self.__class__.__timeout = -1
        self.__class__.__userId = -1
    
    def generateSignature(self,params,requireSession):
        secret=""
        if requireSession and self.isDesktop():
            secret=self.__class__.__sessionSecret
        else:
            secret=self.__class__.__secret
        return utils.generateSignature(params, secret)
    
    def delimit(self,s):
        l=[]
        for i in s:
            l.append(str(i))
        return ','.join(l)
    
    def isDesktop(self):
        return self.__class__.__isDesktop
    
    def getResponseFormat(self):
        return "xml"
    
    def setDebug(self,bool):
        self.__class__.__isDebug=bool
    #utils
    def printDOM(self,n,prefix):
        outString=prefix
        if n.nodeType==Node.TEXT_NODE:
            outString+="'"+n.data.strip()+"'"
        else:
            outString+=n.nodeName
        print outString
        children=n.childNodes
        for child in children:
            self.printDOM(child,prefix+"*")

    def stripEmptyTextNodes(self,n):
        children=n.childNodes
        for child in children:
            if (not child.hasChildNodes()) and child.nodeType==Node.TEXT_NODE and len(child.data.strip())==0:
                children.remove(child)
        for child in children:
            self.stripEmptyTextNodes(child)


def testGetUserInfo():
    client=XiaoneiRestClient(configs.apiKey,configs.secret,configs.sessionKey)
    fields=[profilefield.NAME,profilefield.SEX,
            profilefield.BIRTHDAY,profilefield.HS_HISTORY,profilefield.TINYURL,
            profilefield.HEADURL,profilefield.MAINURL,
            profilefield.HOMETOWN_LOCATION,profilefield.WORK_HISTORY,
            profilefield.UNIVERSITY_HISTORY]
    s=set(fields)
    fields=list(s)
    fields.sort(lambda x,y:cmp(x._order,y._order))
    userids=[111,222]
    client.users_getUserInfo(userids, fields)
    
if __name__=="__main__":
    testGetUserInfo()
    pass
